import json
import time
import aiofiles
import falcon
import uvicorn
import falcon
import falcon.asgi
import logging


from RedisManager import RedisManager
from SessionManager import SessionManager
from SessionMiddleware import SecurityMiddleware, SessionMiddleware
from SessionTypeDefine import JWTPayloadUserPart
from myECDH import (
    ECDHKeyPair,
    compute_derive_key_viab64,
    compute_shared_secret_via64,
    generate_key_pair,
)

logging.basicConfig(level=logging.INFO)
sm = SessionManager()
rm = RedisManager()

#TODO 更换那个钥匙


class Index:
    async def on_get(self, req: falcon.Request, resp: falcon.Response):
        stream = await aiofiles.open("index.html", "r", encoding="utf-8")
        resp.content_type = "text/html"
        resp.text = await stream.read()


class Login:
    async def on_get(self, req: falcon.Request, resp: falcon.Response):
        """模拟访问登录页面时，创建初始空会话"""
        ssid, _ = await sm.create(resp)
        await sm.set(ssid, "test-key", "test-value" + str(time.time()))
        k: ECDHKeyPair = generate_key_pair()
        await sm.set(ssid, "ecdh-pukey", k["publicKeyBase64"])
        await sm.set(ssid, "ecdh-prkey", k["privateKeyBase64"])
        resp.media = {"hello": "world", "k": k["publicKeyBase64"]}

    async def on_post(self, req: falcon.Request, resp: falcon.Response):
        """模拟提交登录表单时，补全填空空会话"""
        shared_key: str = compute_shared_secret_via64(
            await sm.get(req.context.ssid, "ecdh-prkey"), media.get("k")
        )
        derived_key: str = compute_derive_key_viab64(shared_key)
        media: dict = json.loads(await req.bounded_stream.read())

        username: str = media.get("username") or ""
        password: str = media.get("password") or ""

        if type(password) is str:
            # FEAT: 自己做一些账号密码验证策略
            pass
        else:
            raise falcon.HTTPUnauthorized(
                title="密码错误", description="[0x0101]密码错误"
            )
        d: dict | JWTPayloadUserPart = {
            "uid": 0,
            "perms": "",
            "role": "",
        }
        # await sm.session_fill(req, resp, d)
        await sm.fill(req, resp, d)


        resp.media = {
            "things": ["stars"],
            "test:derived_key": derived_key,
            "test:shared_key": shared_key,
        }


class LoginRequired:
    async def on_get(self, req: falcon.Request, resp: falcon.Response):
        resp.media = {"hello": "world2"}

    async def on_post(self, req: falcon.Request, resp: falcon.Response):
        resp.content_type = "application/enc-json"
        resp.media = {
            "hello": "world3",
            "enc-json": "This is a secret server message.",
        }


app = falcon.asgi.App(middleware=[SessionMiddleware(), SecurityMiddleware()])
app.add_route("/", Index())
app.add_route("/login", Login())
app.add_route("/t2", LoginRequired())

if __name__ == "__main__":

    uvicorn.run(app="main:app", host="0.0.0.0", port=8000, reload=True)
